package org.wenhuayuan.library.executor

import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.annotation.IntRange
import java.util.concurrent.*
import java.util.concurrent.atomic.AtomicLong
import java.util.concurrent.locks.Condition
import java.util.concurrent.locks.ReentrantLock

// 全局通用，kt不用使用单例模式。而是使用
// 支持 按任务的优先级执行，支持线程池暂停、恢复（批量文件的下载、上传）
// 异步结果主动回调主线程
object HiExecutor {
    private val TAG: String = "Hi-Executor"
    private var isPaused: Boolean = false
    private var hiExecutor: ThreadPoolExecutor
    private var lock: ReentrantLock
    private var pauseCondition: Condition
    private val mainHandler = Handler(Looper.getMainLooper())
    init {
        lock = ReentrantLock()
        pauseCondition = lock.newCondition()
        val cpucount = Runtime.getRuntime().availableProcessors()
        val corPoolSize = cpucount + 1
        val maxPoolSize = cpucount * 2 + 1
        val blockingQueue: PriorityBlockingQueue<out Runnable> = PriorityBlockingQueue()
        val keepAliveTime = 30L
        val unit = TimeUnit.SECONDS

        val seq = AtomicLong()
        val threadFactory = ThreadFactory{
            val thread = Thread(it)
            thread.name = "hi-executor-" + seq.getAndIncrement()
            return@ThreadFactory thread
        }

        hiExecutor = object: ThreadPoolExecutor(
            corPoolSize,
            maxPoolSize,
            keepAliveTime,
            unit,
            blockingQueue as BlockingQueue<Runnable>,
            threadFactory
        ){
            override fun beforeExecute(t: Thread?, r: Runnable?) {
                if(isPaused) {
                    lock.lock()
                    try {
                        pauseCondition.await()
                    }finally{
                        lock.unlock()
                    }
                }
            }

            override fun afterExecute(r: Runnable?, t: Throwable?) {
                // 监控线程的耗时任务，线程创建数量，正在运行的数量
                Log.e(TAG, "hiexecutor-afterExecute 已执行完毕 任务优先级是："+(r as PriorityRunnable).priority)
            }
        }
    }

    // 使用@JvmOverloads注解，则Kotlin就会暴露多个重载方法
    @JvmOverloads
    fun execute(@IntRange(from = 0, to = 10)priority: Int = 0, runnable: Runnable) {
        hiExecutor.execute(PriorityRunnable(priority, runnable))
    }
    @JvmOverloads
    fun execute(@IntRange(from = 0, to = 10)priority: Int = 0, runnable: Callable<*>) {
        hiExecutor.execute(PriorityRunnable(priority, runnable))
    }

    abstract class Callable<T>: Runnable {
        override fun run() {
            mainHandler.post { onPrepare() }
            val t: T = onBackground()
            mainHandler.post { onCompleted(t) }
        }
        open fun onPrepare() {}
        abstract fun onBackground():T
        abstract fun onCompleted(t: T)
    }

    class PriorityRunnable(val priority: Int, val runnable: Runnable): Runnable, Comparable<PriorityRunnable>{
        override fun compareTo(other: PriorityRunnable): Int {
            return if (this.priority<other.priority) 1 else if (this.priority>other.priority) -1 else 0
        }

        override fun run() {
            runnable.run()
        }
    }

    @Synchronized
    fun pause() {
        isPaused = true
        Log.e(TAG, "hiexecutor is paused")
    }

    @Synchronized
    fun resume() {
        isPaused = false
        Log.e(TAG, "hiexecutor is resume")
        lock.lock()
        try {
            pauseCondition.signalAll()
        }finally{
            lock.unlock()
        }
    }
}